Skip to content

Price the coveringKey refusal's miss with its exception, not as a flat average - #13535

Merged
os-project-manager merged 1 commit into
mainfrom
claude/issue-13467-coveringkey-pricing-exception
Aug 30, 2026
Merged

Price the coveringKey refusal's miss with its exception, not as a flat average#13535
os-project-manager merged 1 commit into
mainfrom
claude/issue-13467-coveringkey-pricing-exception

Conversation

@os-project-manager

Copy link
Copy Markdown
Collaborator

Fixes #13467

coveringKey's refusal docblock priced every missed import-edge lead at "the miss costs one CI round." That sentence is its own named witness's price — scripts/pm/bare-root-worklist.mjs --self-test, whose family lint.yml runs on every PR — and an average over the class. The next reader quotes it as the price of every individual lead. For a minority it is wrong.

What changed

One paragraph in the coveringKey docblock, plus three --self-test assertions that re-derive it. Nothing else: the refusal itself (fifth key, fan-in threshold) is untouched, and so are the five paths-filtered patrol workflows.

The docblock now states the shape and the self-test prints the sizes, because this figure has already been measured at three different values on three different days:

  • the large majority of novel pairs sit in a family at least one unfiltered workflow runs — CI opens that module on this PR whatever the derivation said, so one round really is the whole price;
  • the rest sit in families no every-PR workflow runs, where nothing on the PR repays the miss and the family next executes on its own cadence, detached from the change.

Re-derived, not quoted

The card's numbers are deliberately not carried over. Re-derived on this tree at 90705ffa0, printed live by the new pins:

the "one CI round" price is an average, not a uniform one - 9 of 244 novel
pair(s) sit in families no every-PR workflow runs (cut-rc.yml,
half-state-patrol.yml, prerelease-pin-watch.yml, release-coverage-patrol.yml,
release.yml, required-set-patrol.yml, validate-deps.yml)
...and the deferred pair(s) concentrate on the heads rather than the tail:
8 of 9 land on a module more than 3 families import

The card said 231/10 of 241; today it derives 235/9 of 244. Two things the re-derivation corrected, both now reflected in the prose rather than the card's wording:

  1. ⚠️ The deferral is of the LEAD, not of the load break. The card says a load break in those four helpers "goes green on the PR". Measured, it does not: invoked-as.mjs is imported by 122 families, 118 of which run on every PR (import-prerequisite.mjs 44, workspace-enumerator.mjs 10, check-shard-attestation.mjs 2). A module that fails to load reddens the PR through a sibling. What actually defers is the narrower break — one only the deferred consumer would have seen. This is now a pinned assertion, so the docblock cannot drift back into the stronger claim.
  2. The deferring workflow set is wider than the card's five: cut-rc.yml and release.yml also carry deferred families. The pin prints the live set rather than freezing a list. ⛔ No workflow was edited.

Why pins rather than numbers in prose

The docblock already says its staleness alarms are re-derived every --self-test run. Three assertions were added in that same block:

  • the split itself — green while the deferred half exists and stays a small minority; red if it vanishes (paragraph stale) or grows large (framing understates);
  • the anti-over-read half — every module carrying a deferred pair is also imported by an every-PR family;
  • the concentration — most deferred pairs land on a module more than 3 families import (the tail boundary the aggregate paragraph already uses).

A red in any of them re-prices the paragraph; it does not fault the derivation. That is stated in the comment above them.

Verification

node scripts/pm/dispatch-gates.mjs --self-test: 976 cases before, 979 pass after.

Reverse-verified by two ablations, each mutating the derivation input, each confirmed on disk by blob hash and restored to the exact HEAD blob:

ablation pins reddened
classify no workflow as every-PR split pin ✗ (244 of 244), load-break pin ✗
fan-in threshold raised past every module concentration pin ✗ (0 of 9)

Both restored: git diff HEAD empty, blob back to 6d10cec9.

Gate family derived from the diff by dispatch-gates.mjs --changed --repo objectstack-ai/objectstack (14 families), all run at 90705ffa0, all EXIT=0 with the exit captured before any pipe: check:pm-dispatch-gates · bare-root-worklist.mjs --self-test (this tool's only real static importer — verified: the two .test.ts files mentioning it do so in prose only) · check-self-test-wired · check:agent-test-spelling · check:bash32-floor · check:cli-command-ids · check:cross-package-test-inputs · check:entry-guard · check:parse-guard · check:pnpm-filter-targets · check:watch-hint-literal · check-ci-filter-parity · check-shard-attestation · check:nul-bytes.

check-test-completeness.mjs exits 3 = NOT MEASURED (neither red nor green).

Changeset

None owed — the diff is one file under scripts/pm/**, internal PM tooling that publishes nothing from any package. skip-changeset applied.

Out of scope, deliberately

⛔ The refusal itself is not touched. ⛔ The five paths-filtered patrol workflows are not touched. The card's escalation measurement — whether such a deferred break has ever actually shipped — was not commissioned and was not run; see the report comment for what the fan-in reading above implies about it.


Generated by Claude Code

…t as a flat average

The refusal's COSTS paragraph priced every missed import-edge lead at "one CI
round". That is the price of its own named witness, whose family lint.yml runs
on every PR — but it is an average over the class, and the next reader quotes
it as the price of every individual lead.

State the split instead, and let --self-test print the sizes: the large
majority of novel pairs sit in a family some unfiltered workflow runs, where
one round is the whole price; the rest sit in families no every-PR workflow
runs, where nothing on the PR repays the miss and the family next executes on
its own cadence.

Three assertions re-derive it every run rather than freezing numbers that have
already moved three times: the split itself, the concentration on the shared
heads, and the half that keeps the exception from being over-read — a deferred
pair defers the LEAD, not the load break, because every module carrying one is
imported by every-PR families too.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pk26oZ12t5N1hwGW1m1MgC
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants